##########################################
## Copyright 2012-2013 Ceruti Francesco & contributors
##
## This file is part of LiSP (Linux Show Player).
##########################################

from time import sleep
from math import pow, log10
from threading import Timer

from PyQt4 import QtGui, QtCore

from lisp.core.actions import Action
from lisp.ui.qtimeinputdialog import QTimeInputDialog


class PAction(Action):

    ID = 'None'

    isReversible = False

    hasInfo = True
    hasSettingsUi = False

    def info(self):
        return self.ID

    def __init__(self):
        self.time = 0

    def getTime(self):
        '''For sorting'''
        return self.time

    def showSettingsUi(self):
        pass

    def __repr__(self):
        return str(self.time) + ':' + str(self.ID)

    def fromString(self, string):
        pass


class Play(PAction):

    ID = 'Play'

    def __init__(self, media):
        super(Play, self).__init__()
        self.__media = media

    def do(self):
        self.__media.play()


class Stop(PAction):

    ID = 'Stop'

    def __init__(self, media):
        super(Stop, self).__init__()
        self.__media = media

    def do(self):
        self.__media.stop()


class Pause(PAction):

    ID = 'Pause'

    hasSettingsUi = True

    def __init__(self, media):
        super(Pause, self).__init__()
        self.__media = media
        self.__restart = 0

    def do(self):
        self.__media.pause()
        if(self.__restart > 0):
            Timer(self.__restart, self.__media.play).start()

    def showSettingsUi(self):
        initial = QtCore.QTime(0, (self.__restart / 60000) % 60, (self.__restart / 1000) % 60)
        minValue = QtCore.QTime(0, 0, 0)
        maxValue = QtCore.QTime(0, 59, 59)

        dial = QTimeInputDialog('Pause', 'Insert time before restart (0 = never)', initial, minValue, maxValue)
        dial.exec_()

        if(dial.result() == dial.Accepted):
            self.__restart = dial.time.time().minute() * 60 + dial.time.time().second()

    def __repr__(self):
        return super().__repr__() + ':' + str(self.__restart)

    def fromString(self, string):
        conf = string.split(':')
        self.time = int(conf[0])
        self.__restart = int(conf[2])


class Seek(PAction):

    ID = 'Seek'

    hasSettingsUi = True

    def __init__(self, media):
        super(Seek, self).__init__()
        self.__media = media

        self.__position = 0

    def __repr__(self):
        return super().__repr__() + ':' + str(self.__position)

    def fromString(self, string):
        conf = string.split(':')
        self.time = int(conf[0])
        self.__position = float(conf[2])

    def do(self):
        self.__media.seek(self.__position)

    def showSettingsUi(self):
        initial = QtCore.QTime(0, (self.__position / 60000) % 60, (self.__position / 1000) % 60)
        minValue = QtCore.QTime(0, 0, 0)
        maxValue = QtCore.QTime(0, (self.__media.conf['duration'] / 60000) % 60, (self.__media.conf['duration'] / 1000) % 60)

        dial = QTimeInputDialog('Seek', 'Insert time', initial, minValue, maxValue)
        dial.exec_()

        if(dial.result() == dial.Accepted):
            self.__position = dial.time.time().minute() * 60000 + dial.time.time().second() * 1000


class ToVolume(PAction):

    ID = 'ToVolume'

    hasSettingsUi = True

    def __init__(self, media):
        super(ToVolume, self).__init__()
        self.__media = media

        self.__finalValue = 1
        self.__transition = 0   # in sec/10

    def __repr__(self):
        return super().__repr__() + ':' + str(self.__finalValue) + ':' + str(self.__transition)

    def fromString(self, string):
        conf = string.split(':')
        self.time = int(conf[0])
        self.__finalValue = float(conf[2])
        self.__transition = int(conf[3])

    def showSettingsUi(self):
        if(self.__finalValue == 0):
            current = -100
        else:
            current = log10(self.__finalValue) * 20
        volume = QtGui.QInputDialog.getDouble(None, 'ToVolume', 'Insert volume (dB)', value=current, min=-100, max=10, decimals=2)
        if(volume[1]):
            transition = QtGui.QInputDialog.getInt(None, 'ToVolume', 'Insert fade time (sec/10)', value=self.__transition, min=0, max=1000)
            if(transition[1]):
                self.__finalValue = pow(10, volume[0] / 20)
                self.__transition = transition[0]

    def do(self):
        if(self.__transition == 0):
            self.__media.dPipe['volume'].set_property('volume', self.__finalValue)
        else:
            current = self.__media.dPipe['volume'].get_property('volume')
            value = (self.__finalValue - current) / self.__transition
            for time in range(0, self.__transition):    # @UnusedVariable
                current += value
                self.__media.dPipe['volume'].set_property('volume', current)
                sleep(0.1)


class ToSpeed(PAction):

    ID = 'ToSpeed'

    hasSettingsUi = True

    def __init__(self, media):
        super(ToSpeed, self).__init__()
        self.__media = media

        self.__finalValue = 1
        self.__transition = 0   # in sec/10

    def __repr__(self):
        return super().__repr__() + ':' + str(self.__finalValue) + ':' + str(self.__transition)

    def fromString(self, string):
        conf = string.split(':')
        self.time = int(conf[0])
        self.__finalValue = float(conf[2])
        self.__transition = float(conf[3])

    def showSettingsUi(self):
        speed = QtGui.QInputDialog.getDouble(None, 'ToSpeed', 'Insert speed', value=self.__finalValue, min=0.01, max=10, decimals=2)
        if(speed[1]):
            transition = QtGui.QInputDialog.getInt(None, 'ToVolume', 'Insert transition time (sec/10)', value=self.__transition, min=0, max=1000)
            if(transition[1]):
                self.__finalValue = speed[0]
                self.__transition = transition[0]

    def do(self):
        if(self.__transition == 0):
            self.__media.dPipe['pitch'].set_property('tempo', self.__finalValue)
        else:
            current = self.__media.dPipe['pitch'].get_property('tempo')
            value = (self.__finalValue - current) / self.__transition
            for time in range(0, self.__transition):    # @UnusedVariable
                current += value
                self.__media.dPipe['pitch'].set_property('tempo', current)
                sleep(0.1)
